﻿@using DevExtreme.AspNet.Data.ResponseModel
@using DevExtreme.AspNet.Data
@using System.Threading
@using System.Threading.Tasks
@using System.Net.Http
@using System.Text.Json

<div class="demo-description mw-1100">
    <h2><DemoNavLink Link="BindGridtoData#CustomData" />Custom Data Binding</h2>
    <p>
        If your data is stored in a remote service and is loaded through a Web API, assign the data type to the grid's <b>T</b> parameter and use the <a class="helplink" target="_blank" href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxDataGrid-1.CustomData">CustomData</a> property to implement desired data load logic. This property specifies an asynchronous function that accepts two parameters: a <a class="helplink" target="_blank" href="https://devexpress.github.io/DevExtreme.AspNet.Data/net/api/DevExtreme.AspNet.Data.DataSourceLoadOptionsBase.html">DataSourceLoadOptionsBase</a> object that reflects the current grid state and a <a class="helplink" target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken">CancellationToken</a> object that propagates cancellation notifications.
        In this function, you can use the <a class="helplink" target="_blank" href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DataSourceLoadOptionsExtensions.ConvertToGetRequestUri(DevExtreme.AspNet.Data.DataSourceLoadOptionsBase-System.String)">ConvertToGetRequestUri</a> and <a class="helplink" target="_blank" href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DataSourceLoadOptionsExtensions.ConvertToHttpContent(DevExtreme.AspNet.Data.DataSourceLoadOptionsBase)">ConvertToHttpContent</a> extension methods to generate HTTP requests with parameters based on data load options.
        The function should return a <a class="helplink" target="_blank" href="https://devexpress.github.io/DevExtreme.AspNet.Data/net/api/DevExtreme.AspNet.Data.ResponseModel.LoadResult.html">Task&lt;LoadResult&gt;</a>﻿ object.
    </p>
    <p>
        On the remote service, <a class="helplink" target="_blank" href="http://docs.devexpress.devx/AspNetCore/401020/devextreme-based-controls/concepts/bind-controls-to-data/api-controllers">implement an API controller</a> and create action methods that use the <a class="helplink" target="_blank" href="https://devexpress.github.io/DevExtreme.AspNet.Data/net/api/DevExtreme.AspNet.Data.DataSourceLoader.html">DataSourceLoader</a> class to create a <b>LoadResult</b> object based on load options.
    </p>
    <p>
        In this demo, the Data Grid and the <b>Customer ID</b> and <b>Ship Via</b> combobox columns are bound to a remote Web API service. The <a class="helplink" target="_blank" href="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DataSourceLoadOptionsExtensions.ConvertToGetRequestUri(DevExtreme.AspNet.Data.DataSourceLoadOptionsBase-System.String)">ConvertToGetRequestUri</a> extension method is used to generate a GET request URI with parameters based on data load options. The Web API controller uses the <a class="helplink" target="_blank" href="https://devexpress.github.io/DevExtreme.AspNet.Data/net/api/DevExtreme.AspNet.Data.DataSourceLoader.html">DataSourceLoader.Load</a> method to load data.
    </p>
</div>
<DxDataGrid T="@WebApiOrder" CustomData="@LoadOrderData" ShowFilterRow="true" CssClass="mw-1100">
    <Columns>
        <DxDataGridComboBoxColumn T="@(WebApiCustomerLookup)" TextFieldName="Text" ValueFieldName="Value"
                                  CustomData="@LoadCustomerData" Field="@nameof(WebApiOrder.CustomerID)" Width="300px" />
        <DxDataGridDateEditColumn Field="@nameof(WebApiOrder.OrderDate)" Width="180px" />
        <DxDataGridSpinEditColumn Field="@nameof(WebApiOrder.Freight)" DisplayFormat="c" Width="180px" />
        <DxDataGridColumn Field="@nameof(WebApiOrder.ShipCountry)" Width="210px" />
        <DxDataGridComboBoxColumn T="@(WebApiShipperLookup)" TextFieldName="Text" ValueFieldName="Value"
                                  CustomData="@LoadShipmentData" Field="@nameof(WebApiOrder.ShipVia)" Width="220px" />
    </Columns>
</DxDataGrid>
<CodeSnippet_Grid_DataBinding_CustomDataSource />
@code {
    [Inject] protected HttpClient Client { get; set; }

    protected async Task<LoadResult> LoadOrderData(DataSourceLoadOptionsBase options, CancellationToken cancellationToken)
        => await LoadCustomData("https://js.devexpress.com/Demos/NetCore/api/DataGridWebApi/Orders", options, cancellationToken);
    protected async Task<LoadResult> LoadCustomerData(DataSourceLoadOptionsBase options, CancellationToken cancellationToken)
        => await LoadCustomData("https://js.devexpress.com/Demos/NetCore/api/DataGridWebApi/CustomersLookup", options, cancellationToken);
    protected async Task<LoadResult> LoadShipmentData(DataSourceLoadOptionsBase options, CancellationToken cancellationToken)
        => await LoadCustomData("https://js.devexpress.com/Demos/NetCore/api/DataGridWebApi/ShippersLookup", options, cancellationToken);

    protected async Task<LoadResult> LoadCustomData(string dataEndpointUri, DataSourceLoadOptionsBase options, CancellationToken cancellationToken) {
        using var response = await Client.GetAsync(options.ConvertToGetRequestUri(dataEndpointUri), cancellationToken);
        response.EnsureSuccessStatusCode();
        using var responseStream = await response.Content.ReadAsStreamAsync();
        return await JsonSerializer.DeserializeAsync<LoadResult>(responseStream, cancellationToken: cancellationToken);
    }
}
